//package com.example.common.rc.aop.dicttrans.dictaop;
//
//import cn.hutool.core.bean.BeanUtil;
//import cn.hutool.core.collection.CollUtil;
//import cn.hutool.core.util.ArrayUtil;
//import cn.hutool.core.util.ReflectUtil;
//import cn.hutool.core.util.StrUtil;
//import com.baomidou.mybatisplus.core.metadata.IPage;
//import com.example.common.core.CommonConstant;
//import com.example.common.core.Result;
//import com.example.common.kotlinutil.OptionalUtils;
//import com.example.common.rc.aop.dicttrans.classutil.ByteBuddyUtil;
//import com.example.crud.sys.api.CommonAPI;
//import com.example.crud.sys.model.DictModel;
//import com.fasterxml.jackson.databind.ObjectMapper;
//import java.lang.reflect.Field;
//import java.util.Arrays;
//import java.util.Collection;
//import java.util.List;
//import java.util.Map;
//import java.util.Objects;
//import java.util.Optional;
//import java.util.function.BiFunction;
//import java.util.function.Function;
//import java.util.stream.Collectors;
//import lombok.AllArgsConstructor;
//import lombok.Getter;
//import lombok.SneakyThrows;
//import lombok.extern.slf4j.Slf4j;
//import org.aspectj.lang.ProceedingJoinPoint;
//import org.aspectj.lang.annotation.Around;
//import org.aspectj.lang.annotation.Aspect;
//import org.aspectj.lang.annotation.Pointcut;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.stereotype.Component;
//
///**
// * @Description: 字典aop类
// * @Author: dangzhenghui
// * @Date: 2019-3-17 21:50
// * @Version: 1.0
// */
//@Aspect
//@Component
//@Slf4j
//public class DictAop3 {
//
//    @Autowired
//    ObjectMapper objectMapper;
//
//    //@Lazy
//    @Autowired
//    private CommonAPI commonAPI;
//
//    @Pointcut("execution(* com.example..BaseController.*(..))")
//    public void p1() {
//    }
//
//    @Pointcut("execution(* com.example..*Controller+.*(..))")
//    public void p2() {
//    }
//
//    @Pointcut("execution(* com.example..*Api+.*(..))")
//    public void p3() {
//    }
//
//    /**
//     * 该切面会对实体中属性加了@DictCode2Name注解的字段生效,支持嵌套List<T>属性 T中加了注解的也会被翻译
//     * 只针对包装类型Result<?>返回有效
//     * 只返回实体类型会报错:因为aop不支持改变既有返回类型,只能改变返回内容
//     * Result<?>对于包装内里的类型,改变内容,aop源码中会对最外层包装类进行类型强转(Result<?>),不会报错
//     *
//     * @param pjp           pjp
//     * @param needTransLate 需要翻译
//     * @return {@link Object }
//     * @author zjarlin
//     * @since 2023/01/05
//     */
//    @Around("(p1()||p2()||p3()) &&  @annotation(needTransLate)")
//    @SneakyThrows
//    public Object transLateDict(ProceedingJoinPoint pjp, NeedTransLate needTransLate) {
//        Object proceed = pjp.proceed();
//        if (proceed instanceof Result) {
//            Result result = (Result) proceed;
//            Object outVO = result.getResult();
//            Class<?> aClass = outVO.getClass();
//            //包装类型拆一层即为非包装类型,进行模式匹配
//            BiFunction<Object, Function<Object, ?>, ?> consumerByType = PatternMatching.getConsumerByType(aClass);
//            if (Objects.nonNull(consumerByType)) {
//                Object apply = consumerByType.apply(outVO, this::transOutVO);
//                result.setResult(apply);
//                return result;
//            }
//            /*
//这里非包装类型添加完字段_dictText,已经不是原来的类字段所能接受的啦,再加上aop不可以改变既有返回类型
//除非用字节码技术,对原来的obj中动态添加字段,重构transOutVO方法的返回值为代理Object(增加字段后的对象)
//所以下面的情况基本上是废话(即transLateDict切面仅对包装一层Result生效)
//
//*/
//            result.setResult(this.transOutVO(outVO));
//            return result;
//        }
//        //走到这就是各种非包装类型的,进行模式匹配
//        Class<?> aClass = proceed.getClass();
//
//        BiFunction<Object, Function<Object, ?>, ?> consumerByType = PatternMatching.getConsumerByType(aClass);
//        if (Objects.nonNull(consumerByType)) {
//            Object apply = consumerByType.apply(proceed, this::transOutVO);
//            return apply;
//        }
//        //走到这就是只返回实体类型的
//        Object o = this.transOutVO(proceed);
//        return o;
//    }
//
//    /**
//     * 实体上带有注解的翻译成中文
//     * 使用了字节码技术新的返回对象其实是obj的子类
//     *
//     * @param obj 记录
//     */
//    @SneakyThrows
//    private Object transOutVO(Object obj) {
//        Class<?> aClass = obj.getClass();
//        if (String.class.isAssignableFrom(aClass)) {
//            //单属性String翻译
//            DictCode2Name annotation = aClass.getAnnotation(DictCode2Name.class);
//            return extractSingleAttributeTranslation(annotation.tab(), annotation.codeColumn(), annotation.nameColumn(), annotation.isMulti(), annotation.dicCode(), (String) obj);
//        }
//        /*
//        SerializerFeature.WriteMapNullValue--->   null值也展示
//        Feature.OrderedField---> 按照实体中的字段排序
//        */
////        objectMapper.enable(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS);
////        objectMapper.enable(SerializationFeature.WRITE_NULL_MAP_VALUES);
//
////        String json = objectMapper.writeValueAsString(obj);
////        JSONObject jsonObject = JSON.parseObject(json, Feature.OrderedField, Feature.SupportArrayToBean);
//
//        Field[] declaredFields = obj.getClass().getDeclaredFields();
//        if (ArrayUtil.isEmpty(declaredFields)) {
//            return obj;
//        }
//        //需要添加的字段
//        List<String> collect = Arrays.stream(declaredFields).filter(field -> {
//            Object fieldValue = ReflectUtil.getFieldValue(obj, field);
//            boolean annotationPresent = field.isAnnotationPresent(DictCode2Name.class);
//            boolean nonNull = Objects.nonNull(fieldValue);
//            return annotationPresent && nonNull;
//        }).map(e -> {
//            DictCode2Name annotation1 = e.getAnnotation(DictCode2Name.class);
//            String s = annotation1.deserializeAlias();
//            String s1 = annotation1.nameColumn();
//            String other = e.getName() + CommonConstant.DICT_TEXT_SUFFIX;
//            String s3 = OptionalUtils.orElse(StrUtil::isNotBlank, s, s1, other);
//            return s3;
//        }).collect(Collectors.toList());
//        Class<?> aClassProxy = ByteBuddyUtil.genChildClass(collect, aClass);
//        Object o = aClassProxy.newInstance();
//
//        BeanUtil.copyProperties(obj, o);
//
//        Arrays.stream(declaredFields)
//            .filter(field -> {
//                //如果是集合
//                Object fieldValue = ReflectUtil.getFieldValue(obj, field);
//                boolean isNotEmptyCollection = Collection.class.isAssignableFrom(field.getType()) && CollUtil.isNotEmpty((Collection<?>) fieldValue);
//                boolean annotationPresent = field.isAnnotationPresent(DictCode2Name.class);
//                boolean nonNull = Objects.nonNull(fieldValue);
//                return isNotEmptyCollection || annotationPresent && nonNull;
//            }).forEach(field -> {
//                field.setAccessible(true);
//                //让嵌套属性对象支持翻译
//                boolean isCollection = Collection.class.isAssignableFrom(field.getType());
//                if (isCollection) {
//                    Collection fieldValue = (Collection) ReflectUtil.getFieldValue(obj, field);
//                    Collection collect2 = (Collection) fieldValue.stream().map(this::transOutVO).collect(Collectors.toList());
//                    ReflectUtil.setFieldValue(o, field.getName(), collect2);
//                } else {
//                    DictCode2Name annotation = field.getAnnotation(DictCode2Name.class);
//                    String tab = annotation.tab();
//                    String codeColumn = annotation.codeColumn();
//                    String nameColumn = annotation.nameColumn();
//
//                    boolean isMulti = annotation.isMulti();
//                    String dictCode = Optional.ofNullable(annotation.value()).orElse(annotation.dicCode());
//                    String fieldDictValue = String.valueOf(ReflectUtil.getFieldValue(obj, field));
//                    String s = extractSingleAttributeTranslation(tab, codeColumn, nameColumn, isMulti, dictCode, fieldDictValue);
//
//                    String s1 = annotation.deserializeAlias();
//                    String s2 = annotation.nameColumn();
//                    String other = field.getName() + CommonConstant.DICT_TEXT_SUFFIX;
//
//                    String s3 = OptionalUtils.orElse(StrUtil::isNotBlank, s1, s2, other);
//
//                    ReflectUtil.setFieldValue(o, s3, s);
//                }
//
//            });
//        return o;
//    }
//
//    /**
//     * 提取单属性翻译
//     *
//     * @param tab               选项卡
//     * @param codeColumn        代码列
//     * @param nameColumn        名字列
//     * @param isMulti           该属性值是多个逗号隔开的嘛
//     * @param dictCode          dict字典代码
//     * @param fieldRuntimeValue field属性运行时值 Integer或String
//     * @return {@link String }
//     * @author zjarlin
//     * @since 2023/01/05
//     */
//    private <T> String extractSingleAttributeTranslation(String tab, String codeColumn, String nameColumn, boolean isMulti, String dictCode, T fieldRuntimeValue) {
//        if (StrUtil.isAllBlank(dictCode, tab, codeColumn, nameColumn)) {
//            return String.valueOf(fieldRuntimeValue);
//        }
//        String retStr = "";
//        String fieldRuntimeStrValue = String.valueOf(fieldRuntimeValue);
//
//        codeColumn = StrUtil.toUnderlineCase(codeColumn);
//        nameColumn = StrUtil.toUnderlineCase(nameColumn);
//        //dictCode不空 这仨参数全是空说明是内置字典翻译
//        boolean isUseSysDefaultDict = StrUtil.isNotBlank(dictCode) && StrUtil.isAllBlank(tab, codeColumn, nameColumn);
//
//        //如果不是内置字典的翻译
//
//        if (!isUseSysDefaultDict) {
//            if (!isMulti) {
//                retStr = commonAPI.translateDictFromTable(tab, nameColumn, codeColumn, fieldRuntimeStrValue);
//            } else {
//                //如果是多个用逗号隔开的翻译
//                Map<String, String> relation = commonAPI.translateDictFromTableByKeys(tab, nameColumn, codeColumn, fieldRuntimeStrValue).stream().collect(Collectors.toMap(DictModel::getValue, DictModel::getLabel));
//                String[] split = fieldRuntimeStrValue.split(",");
//                retStr = Arrays.stream(split).map(relation::get).collect(Collectors.joining(","));
//            }
//        } else {
//
//            if (!isMulti) {
//                retStr = commonAPI.translateDict(dictCode, fieldRuntimeStrValue);
//            } else {
//                Map<String, List<DictModel>> stringListMap = commonAPI.translateManyDict(dictCode, fieldRuntimeStrValue);
//                List<DictModel> dictModels = stringListMap.get(dictCode);
//                retStr = dictModels.stream().map(DictModel::getLabel).collect(Collectors.joining(","));
//            }
//        }
//        return retStr;
//    }
//
//    @Getter
//    @AllArgsConstructor
//    //@SuppressWarnings({"all"})
//    public enum PatternMatching {
//        IPAGE(IPage.class, (outVO, translater) -> {
//            IPage iPage = (IPage) outVO;
//            List records = iPage.getRecords();
//            List<Object> dasd = (List<Object>) records.stream().map(x -> {
//                return translater.apply(x);
//            }).collect(Collectors.toList());
//            iPage.setRecords(dasd);
//            return iPage;
//        }),
//
//        LIST(List.class, (outVO, translater) -> {
//            List result = (List) outVO;
//            return (List<Object>) result.stream().map(x -> {
//                return translater.apply(x);
//            }).collect(Collectors.toList());
//        }),
//
//        String(String.class, (outVO, translater) -> {
//            String result = (String) outVO;
//            Object apply = translater.apply(result);
//            return apply;
//        });
//
//        private final Class<?> aClass;
//
//        private final BiFunction<Object, Function<Object, ?>, ?> biFunction;
//
//        public static BiFunction<Object, Function<Object, ?>, ?> getConsumerByType(Class<?> clazz) {
//            return Arrays.stream(PatternMatching.values()).filter(e -> e.getAClass().isAssignableFrom(clazz)).map(PatternMatching::getBiFunction).findAny().orElse(null);
//        }
//
//    }
//
//}
